﻿using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Xml.Serialization;
using weBoard.Properties;
using Color = System.Windows.Media.Color;
using Image = System.Windows.Controls.Image;
using Point = System.Windows.Point;

namespace weBoard
{
    #region Public Enums

    /// <summary>
    /// Currently possible drawing modes
    /// </summary>
    public enum eCurSel
    {
        DrawPoint = 0,
        DrawLine = 1,
        DrawRect = 2,
        DrawEllipse = 3,
        DrawPolygon = 4,
        DrawPath = 5,
        DrawPolyline = 6,
        Select = 7
    };

    /// <summary>
    /// Types of operational objects
    /// </summary>
    public enum weObjType
    {
        ObjPoint, 
        ObjEllipse, 
        ObjLine, 
        ObjRect, 
        ObjPath, 
        ObjPolygon, 
        ObjPolyline
    };

    /// <summary>
    /// Types of possible actions
    /// </summary>
    public enum weActType
    {
        Create,
        Delete,
        Move,
        Resize,
        Recolor
    }
    #endregion Public Enums

    #region Serializable classes
    /// <summary>
    /// Represents record of an action
    /// </summary>
    [Serializable]
    public class weBoardAction
    {
        [XmlElement("Act")]
        public weActType Act;
        [XmlElement("Object")]
        public weObjType Object;
        [XmlElement("Uid")]
        public String Uid;
        [XmlElement("Was")]
        public weBoardState Was;
        [XmlElement("Now")]
        public weBoardState Now;
        [XmlElement("Record")]
        public bool Record;
    }

    [Serializable]
    [XmlInclude(typeof(SolidColorBrush))]
    [XmlInclude(typeof(MatrixTransform))]
    public class weBoardState
    {
        [XmlElement("CoordsA")]
        public Point CoordsA;
        [XmlElement("CoordsB")]
        public Point CoordsB;
        [XmlElement("Fill")]
        public Brush Fill;
        [XmlElement("Width")]
        public double Width;
        [XmlElement("Height")]
        public double Height;
        [XmlElement("Text")]
        public String Text;
        [XmlElement("MetaProperties")]
        public object MetaProperties;
    }
    #endregion Serializable classes

    #region Static helper functions
    /// <summary>
    /// Static class with misc. helper weBoard functions
    /// </summary>
    public static class weBoardRoutines
    {
        /// <summary>
        /// Gets host ip in local network 
        /// </summary>
        /// <returns>Local IP address</returns>
        public static string GetLocalIp()
        {
            var host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (var ip in host.AddressList)
            {
                var localIp = ip.ToString();
                var temp = localIp.Split('.');
                if (ip.AddressFamily == AddressFamily.InterNetwork &&
                    (temp[0] == "192" || temp[0] == "10" || temp[0] == "169" || temp[0] == "172"))
                    return ip.ToString();
            }
            return null;
        }

        public static Color GetColorAtMousePoint(Image src)
        {
            var pixels = new byte[4];
            try
            {
                var x = (int) Mouse.GetPosition(src).X;
                var y = (int) Mouse.GetPosition(src).Y;
                if (x == (int) src.ActualWidth)
                    x--;
                if (y == (int) src.ActualHeight)
                    y--;
                var cb = new CroppedBitmap(src.Source as BitmapSource,
                    new Int32Rect(x, y, 1, 1));

                cb.CopyPixels(pixels, 4, 0);
                return Color.FromRgb(pixels[2], pixels[1], pixels[0]);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("GetColorAtMousePoint::Exception occured:" + ex.Message);
                return Color.FromRgb(pixels[2], pixels[1], pixels[0]);
            }
        }
        
        /// <summary>
        /// Gets cursor from internal resource
        /// </summary>
        /// <param name="resName">Name of resource containing cursor</param>
        /// <returns></returns>
        public static Cursor GetCursor(string resName)
        {
            try
            {
                var buffer = Resources.ResourceManager.GetObject(resName) as byte[];
                var m = new MemoryStream(buffer);
                return new Cursor(m);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("GetCursor::Exception occured:" + ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Gets image that corresponds given resourse string
        /// </summary>
        /// <param name="resStr">Resourse string</param>
        /// <returns>required image</returns>
        public static BitmapImage GetImage(String resStr)
        {
            try
            {
                var result = new BitmapImage();
                result.BeginInit();
                result.UriSource = new Uri(resStr, UriKind.Relative);
                result.EndInit();
                return result;
            }
            catch (Exception ex)
            {
                Debug.WriteLine("GetImage::Exception occured:" + ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Returns the optimal selection color based on background and object colors
        /// </summary>
        /// <param name="src1">Color 1 to blend</param>
        /// <param name="src2">Color 2 to blend</param>
        /// <returns></returns>
        public static Color GetMedInvColor(Color src1, Color src2)
        {
            return Color.FromArgb((byte)((src1.A + src2.A) / 2), (byte)(255 - (src1.R + src2.R) / 2), (byte)(255 - (src1.G + src2.G) / 2), (byte)(255 - (src1.B + src2.B) / 2));
        }
    }
    #endregion Static helper functions
}